{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deep Q-Network Variant Categorical 51-Atom DQN (C-51) implementation (PyTorch).\n",
    "\n",
    "In this notebook, we will implement C51 (Categorical DQN) variant of DQN. First part of the notebook is all about the vanilla DQN and how we train - a copy of `6_1_dqn_pytorch.ipynb`. The C51 variant is after these sections on vanilla DQN.\n",
    "\n",
    "\n",
    "### RECAP\n",
    "\n",
    "$$ \n",
    "\\DeclareMathOperator*{\\max}{max}$$\n",
    "\n",
    "Q Learning control is carried out by sampling step by step and updating Q values at each step. We use ε-greedy policy to explore and generate samples. However, the policy learnt is a deterministic greedy policy with no exploration. We can carryout updates online i.e. we take a step and use `(current state, action, reward and next_state)` tuple to update. \n",
    "\n",
    "In case of function approximation using neural network, the input to the network is the state and output is the q(s,a) for all the actions in the state `s`. It is denoted as $ \\hat{q}(s_t,a; w_{t}) $, where $w_{t}$ is the weights of the neural network which we are trying to learn as part of DQN learning. \n",
    "\n",
    "We use two networks, one target network to get the max q-value of next state denoted by $ \\max_a \\hat {q}(s_{t+1},a; w^{-}_{t}) $ and the primary network with weights $w_{t}$ which we are updated based on back propagation of the TD error through the network.\n",
    "\n",
    "The Update equation is given below. This is the online version:\n",
    "$$ w_{t+1} \\leftarrow w_t + \\alpha [ R_{t+1} + \\gamma . \\max_{a} \\hat{q}(S_{t+1},a,w^{-}_{t}) – \\hat{q}(S_t,A_t,w_t)] \\nabla \\hat{q}(S_t,A_t,w_t)$$\n",
    "\n",
    "Online update with neural network with millions of weights does not work well. Accordingly, We use experience replay (aka Replay Buffer).  We use a behavior policy to explore the environment and store the samples `(s, a, r, s', done)` in a buffer. The samples are generated using an exploratory behavior policy while we improve a deterministic target policy using q-values. \n",
    "\n",
    "Therefore, we can always use older samples from behavior policy and apply them again and again. We can keep the buffer size fixed to some pre-determined size and keep deleting the older samples as we collect new ones. This process makes learning sample efficient by reusing a sample multiple times and also removing temporal dependence of the samples we would otherwise see while following a trajectory.\n",
    "\n",
    "The update equation with batch update with minor modifications is given below. We collect samples of transitions (current state, action, reward, next state) in a buffer. Where each sample is denoted as a tuple: \n",
    "\n",
    "$$ (s_{i}, a_{i}, r_{i}, s^{'}_{i}, done_{i})$$\n",
    "\n",
    "Subscript (i) denotes ith sample. We take N samples from experience replay selecting randomly and update the weights. Subscript (t) denotes the index of weight updates. If the current state is done, as denoted by `done` flag, the target is just the reward as terminal states have zero value. The final update equation is as given below:\n",
    "\n",
    "$$w_{t+1} \\leftarrow w_t + \\alpha \\frac{1}{N} \\sum_{i=1}^{N} \\left[ r_i + \\left( (1-done_i) . \\gamma .  \\max_{a^{'}} \\hat{q}(s_{i}^{'},a^{'};w^{-}_{t}) \\right) – \\hat{q}(s_i,a_i;w_t) \\right] \\nabla \\hat{q}(s_i,a_i;w_t)$$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "\n",
    "import gym\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy.signal import convolve, gaussian\n",
    "import math\n",
    "import os\n",
    "import io\n",
    "import base64\n",
    "import time\n",
    "from tqdm import trange\n",
    "import glob\n",
    "import random\n",
    "from collections import namedtuple\n",
    "\n",
    "from IPython.display import HTML, clear_output\n",
    "\n",
    "%matplotlib inline\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Environment - CartPole \n",
    "\n",
    "We can use the setup here to run on any environment which has state as a single vector and actions are discrete. We will build it on Cart Pole and they try to run this on many other environments like Lunar Lander and others.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_env(env_name, seed=None):\n",
    "    # remove time limit wrapper from environment\n",
    "    env = gym.make(env_name).unwrapped\n",
    "    if seed is not None:\n",
    "        env.seed(seed)\n",
    "    return env"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ENV_NAME = 'CartPole-v1'\n",
    "\n",
    "env = make_env(ENV_NAME)\n",
    "env.reset()\n",
    "plt.imshow(env.render(\"rgb_array\"))\n",
    "state_shape, n_actions = env.observation_space.shape, env.action_space.n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Building a network using pytorch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us build a DQN agent using a simple network. We now need to build a neural network that can map states/observations to state q-values. The observation space and action space is as given below for CartPole\n",
    "\n",
    "    Observation:\n",
    "        Type: Box(4)\n",
    "        Num     Observation               Min                     Max\n",
    "        0       Cart Position             -4.8                    4.8\n",
    "        1       Cart Velocity             -Inf                    Inf\n",
    "        2       Pole Angle                -0.418 rad (-24 deg)    0.418 rad (24 deg)\n",
    "        3       Pole Angular Velocity     -Inf                    Inf\n",
    "    Actions:\n",
    "        Type: Discrete(2)\n",
    "        Num   Action\n",
    "        0     Push cart to the left\n",
    "        1     Push cart to the right\n",
    "        \n",
    "\n",
    "The model will be a simple one with 2 hidden payers with Relu activation and final layer being logits with dimension equation to number of actions. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cpu')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DQNAgent(nn.Module):\n",
    "    def __init__(self, state_shape, n_actions, epsilon=0):\n",
    "\n",
    "        super().__init__()\n",
    "        self.epsilon = epsilon\n",
    "        self.n_actions = n_actions\n",
    "        self.state_shape = state_shape\n",
    "        \n",
    "        state_dim = state_shape[0]\n",
    "        # a simple NN with state_dim as input vector (inout is state s)\n",
    "        # and self.n_actions as output vector of logits of q(s, a)\n",
    "        self.fc1 = nn.Linear(state_dim, 64)\n",
    "        self.fc2 = nn.Linear(64, 128)\n",
    "        self.fc3 = nn.Linear(128, 32)\n",
    "        self.q = nn.Linear(32, n_actions)\n",
    "        \n",
    "    def forward(self, state_t):\n",
    "        # pass the state at time t through the newrok to get Q(s,a)\n",
    "        x = F.relu(self.fc1(state_t))\n",
    "        x = F.relu(self.fc2(x))\n",
    "        x = F.relu(self.fc3(x))\n",
    "        qvalues = self.q(x)\n",
    "        return qvalues\n",
    "\n",
    "    def get_qvalues(self, states):\n",
    "        # input is an array of states in numpy and outout is Qvals as numpy array\n",
    "        states = torch.tensor(states, device=device, dtype=torch.float32)\n",
    "        qvalues = self.forward(states)\n",
    "        return qvalues.data.cpu().numpy()\n",
    "\n",
    "    def sample_actions(self, qvalues):\n",
    "        # sample actions from a batch of q_values using epsilon greedy policy\n",
    "        epsilon = self.epsilon\n",
    "        batch_size, n_actions = qvalues.shape\n",
    "        random_actions = np.random.choice(n_actions, size=batch_size)\n",
    "        best_actions = qvalues.argmax(axis=-1)\n",
    "        should_explore = np.random.choice(\n",
    "            [0, 1], batch_size, p=[1-epsilon, epsilon])\n",
    "        return np.where(should_explore, random_actions, best_actions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent = DQNAgent(state_shape, n_actions, epsilon=0.5).to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate(env, agent, n_games=1, greedy=False, t_max=10000):\n",
    "    rewards = []\n",
    "    for _ in range(n_games):\n",
    "        s = env.reset()\n",
    "        reward = 0\n",
    "        for _ in range(t_max):\n",
    "            qvalues = agent.get_qvalues([s])\n",
    "            action = qvalues.argmax(axis=-1)[0] if greedy else agent.sample_actions(qvalues)[0]\n",
    "            s, r, done, _ = env.step(action)\n",
    "            reward += r\n",
    "            if done:\n",
    "                break\n",
    "\n",
    "        rewards.append(reward)\n",
    "    return np.mean(rewards)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "11.0\n"
     ]
    }
   ],
   "source": [
    "print(evaluate(env, agent, n_games=1))\n",
    "env.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Experience replay\n",
    "\n",
    "We will use the replay buffer we saw in chapter 4 listings. Replay buffer is very important in DQN to break the correlation between samples. We use a behavior policy (epsilon greedy) to sample from the environment and store the transitions (s,a,r,s',done) into a buffer. These samples are used multiple times in a learning making the process sample efficient. \n",
    "\n",
    "The interface to ReplayBuffer is:\n",
    "* `exp_replay.add(state, action, reward, next_state, done)` - saves (s,a,r,s',done) tuple into the buffer\n",
    "* `exp_replay.sample(batch_size)` - returns states, actions, rewards, next_states and done_flags for `batch_size` random samples.\n",
    "* `len(exp_replay)` - returns number of elements stored in replay buffer.\n",
    "\n",
    "We have modified the implementation a bit to make it more efficient"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    def __init__(self, size):\n",
    "        self.size = size #max number of items in buffer\n",
    "        self.buffer =[] #array to holde buffer\n",
    "        self.next_id = 0\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self.buffer)\n",
    "    \n",
    "    def add(self, state, action, reward, next_state, done):\n",
    "        item = (state, action, reward, next_state, done)\n",
    "        if len(self.buffer) < self.size:\n",
    "           self.buffer.append(item)\n",
    "        else:\n",
    "            self.buffer[self.next_id] = item\n",
    "        self.next_id = (self.next_id + 1) % self.size\n",
    "        \n",
    "    def sample(self, batch_size):\n",
    "        idxs = np.random.choice(len(self.buffer), batch_size)\n",
    "        samples = [self.buffer[i] for i in idxs]\n",
    "        states, actions, rewards, next_states, done_flags = list(zip(*samples))\n",
    "        return np.array(states), np.array(actions), np.array(rewards), np.array(next_states), np.array(done_flags)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def play_and_record(start_state, agent, env, exp_replay, n_steps=1):\n",
    "\n",
    "    s = start_state\n",
    "    sum_rewards = 0\n",
    "\n",
    "    # Play the game for n_steps and record transitions in buffer\n",
    "    for _ in range(n_steps):\n",
    "        qvalues = agent.get_qvalues([s])\n",
    "        a = agent.sample_actions(qvalues)[0]        \n",
    "        next_s, r, done, _ = env.step(a)\n",
    "        sum_rewards += r\n",
    "        exp_replay.add(s, a, r, next_s, done)\n",
    "        if done:\n",
    "            s = env.reset()\n",
    "        else:\n",
    "            s = next_s\n",
    "        \n",
    "    return sum_rewards, s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Target network\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target_network = DQNAgent(agent.state_shape, agent.n_actions, epsilon=0.5).to(device)\n",
    "target_network.load_state_dict(agent.state_dict())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Learning with... Q-learning\n",
    "Here we write a function similar to tabular q-learning. We will calculate average TD error per batch using the equation: \n",
    "\n",
    "$$ L =  \\frac{1}{N} \\sum_{i=1}^{N} \\left[ r_i + \\left( (1-done_i) . \\gamma .  \\max_{a^{'}} \\hat{q}(s_{i}^{'},a^{'};w^{-}_{t}) \\right) – \\hat{q}(s_i,a_i;w_t) \\right]^2$$\n",
    "\n",
    "\n",
    "$$ \\nabla_w L =   - \\frac{1}{N} \\sum_{i=1}^{N} \\left[ r_i + \\left( (1-done_i) . \\gamma .  \\max_{a^{'}} \\hat{q}(s_{i}^{'},a^{'};w^{-}_{t}) \\right) – \\hat{q}(s_i,a_i;w_t) \\right] \\nabla \\hat{q}(s_i,a_i;w_t)$$\n",
    "\n",
    "\n",
    "$\\hat{q}(s',A;w^{-})$ is calculated using target network whose weights are held constant and refreshed periodically from the agent learning network. \n",
    "\n",
    "Target is given by following:\n",
    "* non terminal state: $r_i +  \\gamma .  \\max_{a^{'}} \\hat{q}(s_{i}^{'},a^{'};w^{-}_{t})$\n",
    "* terminal state: $ r_i $\n",
    "\n",
    "We then carryout back propagation through the agent network to update the weights using equation below:\n",
    "\n",
    "\n",
    "$$ \n",
    "\\DeclareMathOperator*{\\max}{max} w_{t+1} \\leftarrow w_t - \\alpha \\nabla_{w}L$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def td_loss_dqn(agent, target_network, states, actions, rewards, next_states, done_flags,\n",
    "                    gamma=0.99, device=device):\n",
    "\n",
    "    # convert numpy array to torch tensors\n",
    "    states = torch.tensor(states, device=device, dtype=torch.float)\n",
    "    actions = torch.tensor(actions, device=device, dtype=torch.long)\n",
    "    rewards = torch.tensor(rewards, device=device, dtype=torch.float)\n",
    "    next_states = torch.tensor(next_states, device=device, dtype=torch.float)\n",
    "    done_flags = torch.tensor(done_flags.astype('float32'),device=device,dtype=torch.float)\n",
    "\n",
    "    # get q-values for all actions in current states\n",
    "    # use agent network\n",
    "    q_s = agent(states)\n",
    "\n",
    "    # select q-values for chosen actions\n",
    "    q_s_a = q_s[range(\n",
    "        len(actions)), actions]\n",
    "\n",
    "    with torch.no_grad():\n",
    "        # compute q-values for all actions in next states\n",
    "        # use target network\n",
    "        q_s1 = target_network(next_states)\n",
    "\n",
    "\n",
    "        # compute Qmax(next_states, actions) using predicted next q-values\n",
    "        q_s1_a1max,_ = torch.max(q_s1, dim=1)\n",
    "\n",
    "        # compute \"target q-values\" \n",
    "        target_q = rewards + gamma * q_s1_a1max * (1-done_flags)\n",
    "\n",
    "    # mean squared error loss to minimize\n",
    "    loss = torch.mean((q_s_a - target_q.detach()) ** 2)\n",
    "\n",
    "    return loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def epsilon_schedule(start_eps, end_eps, step, final_step):\n",
    "    return start_eps + (end_eps-start_eps)*min(step, final_step)/final_step\n",
    "\n",
    "def smoothen(values):\n",
    "    kernel = gaussian(100, std=100)\n",
    "    kernel = kernel / np.sum(kernel)\n",
    "    return convolve(values, kernel, 'valid')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Main loop\n",
    "\n",
    "We now carryout the training on DQN setup above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_agent(env, agent, target_network, optimizer, td_loss_fn):\n",
    "    \n",
    "    state = env.reset()\n",
    "    # let us fill experience replay with some samples using full random policy\n",
    "    exp_replay = ReplayBuffer(10**4)\n",
    "    for i in range(100):\n",
    "        play_and_record(state, agent, env, exp_replay, n_steps=10**2)\n",
    "        if len(exp_replay) == 10**4:\n",
    "            break\n",
    "    print('Finished filling buffer with: {} samples'.format(len(exp_replay)))\n",
    "\n",
    "    mean_rw_history = []\n",
    "    td_loss_history = []\n",
    "    state = env.reset()\n",
    "    for step in trange(total_steps + 1):\n",
    "\n",
    "        # reduce exploration as we progress\n",
    "        agent.epsilon = epsilon_schedule(start_epsilon, end_epsilon, step, eps_decay_final_step)\n",
    "\n",
    "        # take timesteps_per_epoch and update experience replay buffer\n",
    "        _, state = play_and_record(state, agent, env, exp_replay, timesteps_per_epoch)\n",
    "\n",
    "        # train by sampling batch_size of data from experience replay\n",
    "        states, actions, rewards, next_states, done_flags = exp_replay.sample(batch_size)\n",
    "\n",
    "\n",
    "        # loss = <compute TD loss>\n",
    "        optimizer.zero_grad()\n",
    "        loss = td_loss_fn(agent, target_network, \n",
    "                          states, actions, rewards, next_states, done_flags,                  \n",
    "                          gamma=0.99,\n",
    "                          device=device)\n",
    "\n",
    "        loss.backward()\n",
    "        grad_norm = nn.utils.clip_grad_norm_(agent.parameters(), max_grad_norm)\n",
    "        optimizer.step()\n",
    "\n",
    "        if step % loss_freq == 0:\n",
    "            td_loss_history.append(loss.data.cpu().item())\n",
    "\n",
    "        if step % refresh_target_network_freq == 0:\n",
    "            # Load agent weights into target_network\n",
    "            target_network.load_state_dict(agent.state_dict())\n",
    "\n",
    "        if step % eval_freq == 0:\n",
    "            # eval the agent\n",
    "            mean_rw_history.append(evaluate(\n",
    "                make_env(ENV_NAME, seed=step), agent, n_games=3, greedy=True, t_max=1000)\n",
    "            )\n",
    "\n",
    "            clear_output(True)\n",
    "            print(\"buffer size = %i, epsilon = %.5f\" %\n",
    "                  (len(exp_replay), agent.epsilon))\n",
    "\n",
    "            plt.figure(figsize=[16, 5])\n",
    "            plt.subplot(1, 2, 1)\n",
    "            plt.title(\"Mean reward per episode\")\n",
    "            plt.plot(mean_rw_history)\n",
    "            plt.grid()\n",
    "\n",
    "            assert not np.isnan(td_loss_history[-1])\n",
    "            plt.subplot(1, 2, 2)\n",
    "            plt.title(\"TD loss history (smoothened)\")\n",
    "            plt.plot(smoothen(td_loss_history))\n",
    "            plt.grid()\n",
    "\n",
    "            plt.show()\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "#setup some parameters for training\n",
    "timesteps_per_epoch = 1\n",
    "batch_size = 32\n",
    "total_steps = 3 * 10**4\n",
    "\n",
    "# set exploration epsilon \n",
    "start_epsilon = 1\n",
    "end_epsilon = 0.05\n",
    "eps_decay_final_step = 2 * 10**4\n",
    "\n",
    "# setup spme frequency for loggind and updating target network\n",
    "loss_freq = 50\n",
    "refresh_target_network_freq = 100\n",
    "eval_freq = 1000\n",
    "\n",
    "# to clip the gradients\n",
    "max_grad_norm = 5000\n",
    "\n",
    "#set up random numbers\n",
    "seed=0\n",
    "random.seed(seed)\n",
    "np.random.seed(seed)\n",
    "torch.manual_seed(seed) \n",
    "\n",
    "#init environment\n",
    "ENV_NAME = 'CartPole-v1'\n",
    "env = make_env(ENV_NAME, seed)\n",
    "state_dim = env.observation_space.shape\n",
    "n_actions = env.action_space.n\n",
    "\n",
    "#init agent, target network and Optimizer\n",
    "agent = DQNAgent(state_dim, n_actions, epsilon=1).to(device)\n",
    "target_network = DQNAgent(state_dim, n_actions, epsilon=1).to(device)\n",
    "target_network.load_state_dict(agent.state_dict())\n",
    "optimizer = torch.optim.Adam(agent.parameters(), lr=1e-4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "buffer size = 10000, epsilon = 0.05000\n"
     ]
    },
    {
     "data": {
      "image/png": "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cYfjMUN4Hnc4HjP477iNMVpsfYR0bh5daiPfqJ18o3YanNrIN/5sp7OdmzV8V0RERERERByjpFREREREREQco6RUREREREREHKOkVERERERERByjpFREREREREQco6RUREREREREHKOkVERERERERByjpFREREREREQco6RUREREREREHKOkNMgcrGqmtKbV6TBEREREgs6h+m7qW11OhyEifqakNMh84dHtfP2JnU6HISIiIhJUXF1uvvdGO7f9ebPToYiIn0U5HYC8zVrLoaoWEmPbnQ5FREREJKhUNLQBsL203tlARMTv1FMaRE42ddDW2U11s4vaFg1NEREREelRVudJSiOMw4GIiN8pKQ0iR/vMJT1Q2eRgJCIiIiLB5Vit53tSdKS+voqEGv2vDiJHa1p6fy9WUioiIiLSq6en1KinVCTkKCkNIqU1rURGGJJiozhQ2ex0OCIiIiJBwVrLvhOeC/btnW6aO7ocjkhE/ElJaRA5WtPCpPR4ZuYkafiuiIiIiNe/dhxnzd5KYrzfXL/5xE6qGlUYUiRUKCkNIiU1rUzOTGRmTjLFVeopFREREQE4VNVChIGvLY8D4F87yrWEnkgIUVIaJKy1HK1poSAzgRk5ydS2uKhu7nA6LBERERHHNbV3khwXzdS0SF75r0u4al6OpjqJhBAlpUGirrWTpvYu8jMTmZmTBKgCr4iIiAhAY3sXKfFRAEzOTGB6dhLl9W10u63DkYmIPygpDRIl3sq7BZkJzMxJBqBYVwBFRGQIjDGzjDE7+vxrNMZ8wRiTYYxZbYwp9v5MdzpWkaFoau8kOTa69/ak9AS63JaKhjYHoxIRf1FSGiRKvGuU5mcmkJ0cS3JclHpKRURkSKy1+621i621i4GlQCvwBPA1YK21dgaw1ntbZMxobHu7pxRgUkYCAMdq305K3W7LN57YySU/LuK6X67nWG0rbvWkiowJPiWlxpijxpid3quuW7zbBrzqaoy5yxhz0Biz3xhzVaCCDyVHa1owBvLSEzDGeIodqadURESG7zLgkLW2BLgReMC7/QHgJqeCEhmORu+c0h6T0j1J6ft//wa1LS6OVLfwjX/t4sGNpUzJSqS0ppV3/vo15n77eZ7ccdypsEXER0PpKb3Ee/V1mfd2v1ddjTFzgVuAecDVwK+NMZF+jDkkldS0MiE1nrhoT1PNzEni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\n",
      "text/plain": [
       "<Figure size 1152x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████████████████████████████████████████| 30001/30001 [02:39<00:00, 188.40it/s]\n"
     ]
    }
   ],
   "source": [
    "train_agent(env, agent, target_network, optimizer, td_loss_fn=td_loss_dqn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "final score: 281.6666666666667\n"
     ]
    }
   ],
   "source": [
    "final_score = evaluate(\n",
    "  make_env(ENV_NAME),\n",
    "  agent, n_games=30, greedy=True, t_max=1000\n",
    ")\n",
    "print('final score:', final_score)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Let us record a video of trained agent**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_animation(env, agent, save_dir):\n",
    "    \n",
    "    try:\n",
    "        env = gym.wrappers.Monitor(\n",
    "            env, save_dir, video_callable=lambda id: True, force=True, mode='evaluation')\n",
    "    except gym.error.Error as e:\n",
    "        print(e)\n",
    "\n",
    "    if not os.path.exists(save_dir):\n",
    "        os.makedirs(save_dir)\n",
    "        \n",
    "    state = env.reset()\n",
    "    reward = 0\n",
    "    while True:\n",
    "        qvalues = agent.get_qvalues([state])\n",
    "        action = qvalues.argmax(axis=-1)[0]\n",
    "        state, r, done, _ = env.step(action)\n",
    "        reward += r\n",
    "        if done:\n",
    "            print('Got reward: {}'.format(reward))\n",
    "            break\n",
    "            \n",
    "def display_animation(filepath):\n",
    "    video = io.open(filepath, 'r+b').read()\n",
    "    encoded = base64.b64encode(video)\n",
    "    return HTML(data='''<video alt=\"test\" controls>\n",
    "                <source src=\"data:video/mp4;base64,{0}\" type=\"video/mp4\" />\n",
    "                 </video>'''.format(encoded.decode('ascii')))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Got reward: 292.0\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<video alt=\"test\" controls>\n",
       "                <source src=\"data:video/mp4;base64,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AAACAAAAAQAAAPsAAAkAY3R0cwAAAAAAAAEeAAAAAQAAAgAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABAAAAAACAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAAAwAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAIA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\" type=\"video/mp4\" />\n",
       "                 </video>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Animate learned policy\n",
    "save_dir='./videos/pytorch/6_7/'\n",
    "env = make_env(ENV_NAME)\n",
    "generate_animation(env, agent, save_dir=save_dir)\n",
    "[filepath] = glob.glob(os.path.join(save_dir, '*.mp4'))\n",
    "display_animation(filepath)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Categorical 51-Atom DQN (C-51)\n",
    "\n",
    "In the paper, https://arxiv.org/pdf/1707.06887.pdf , authors of the paper use a different route of distributional RL. Till now we have been outputting Q(s,a) values for an input state `s`. The number of units in output were of size `n_action`. In a way the output values were expected Q(s,a) using monte-carlo technique of averaging over a number of samples to form an estimate $\\hat Q(s,a)$ of the actual expected value $E[Q(s,a)]$. \n",
    "\n",
    "In Categorical 51-Atom DQN, for each Q(s,a) (`n_action` of them), we now produce an estimate of the distribution of Q(s,a) values - `n_atom` values for each q(s,a). We are now trying to predict the entire distribution modeled as a categorical probability distribution instead of just estimating the mean value of Q(s,a). \n",
    "\n",
    "$$ Q(s,a) = \\sum_i z_i p_i(s,a)$$ \n",
    "\n",
    "$p_i(s,a)$ is the probability that action-value at (s,a) will be $z_i$. \n",
    "\n",
    "We now have `n_action * n_atom` outputs, i.e. `n_atom` outputs for each value of `n_action`. Further these outputs are probabilities. For one action, we have `n_atom` probabilities and these are the probability of Q_value being in `-n_atom` discrete values in the range `V_min` to `V_max`. You can refer to the text or the linked paper above for more details. \n",
    "\n",
    "In C51 version of **distributional RL**, the authors took $i$ to be 51 atoms (support points) over the values -10 to 10. We will use the same setup in code below. As these values are parameterized in the code, you are welcomed to change these and explore the impact.\n",
    "\n",
    "After bellman updates are applied, the values shift and there is a step of **projection** to bring back the probability distribution of Q(s,a) to the support points of **atoms**. \n",
    "\n",
    "The loss is also replaced from mean squared error to cross-entropy error. The agent is trained using a epsilon-greedy policy, similar to DQN. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "class CategoricalDQN(nn.Module):\n",
    "    def __init__(self, state_shape, n_actions, n_atoms=51, Vmin=-10, Vmax=10, epsilon=0):\n",
    "        \n",
    "        super(CategoricalDQN, self).__init__()\n",
    "        self.epsilon = epsilon\n",
    "        self.n_actions = n_actions\n",
    "        self.state_shape = state_shape        \n",
    "        state_dim = state_shape[0]\n",
    "        self.n_atoms = n_atoms\n",
    "        self.Vmin = Vmin\n",
    "        self.Vmax = Vmax\n",
    "        # a simple NN with state_dim as input vector (inout is state s)\n",
    "        # and self.n_actions as output vector of logits of q(s, a)\n",
    "        self.fc1 = nn.Linear(state_dim, 64)\n",
    "        self.fc2 = nn.Linear(64, 128)\n",
    "        self.fc3 = nn.Linear(128, 32)\n",
    "        self.probs = nn.Linear(32, n_actions * n_atoms)\n",
    "        \n",
    "    def forward(self, state_t):\n",
    "        # pass the state at time t through the newrok to get Q(s,a)\n",
    "        x = F.relu(self.fc1(state_t))\n",
    "        x = F.relu(self.fc2(x))\n",
    "        x = F.relu(self.fc3(x))\n",
    "        probs = F.softmax(self.probs(x).view(-1, self.n_actions, self.n_atoms), dim=-1)\n",
    "        return probs\n",
    "\n",
    "    def get_probs(self, states):\n",
    "        # input is an array of states in numpy and outout is Qvals as numpy array\n",
    "        states = torch.tensor(states, device=device, dtype=torch.float32)\n",
    "        probs = self.forward(states)\n",
    "        return probs.data.cpu().numpy()\n",
    "\n",
    "    def get_qvalues(self, states):\n",
    "        # input is an array of states in numpy and outout is Qvals as numpy array\n",
    "        states = torch.tensor(states, device=device, dtype=torch.float32)\n",
    "        probs = self.forward(states)\n",
    "        support = torch.linspace(self.Vmin, self.Vmax, self.n_atoms)\n",
    "        qvals = support * probs\n",
    "        qvals = qvals.sum(-1)\n",
    "        return qvals.data.cpu().numpy()\n",
    "\n",
    "    def sample_actions(self, qvalues):\n",
    "        # sample actions from a batch of q_values using epsilon greedy policy\n",
    "        epsilon = self.epsilon\n",
    "        batch_size, n_actions = qvalues.shape\n",
    "        random_actions = np.random.choice(n_actions, size=batch_size)\n",
    "        best_actions = qvalues.argmax(axis=-1)\n",
    "        should_explore = np.random.choice(\n",
    "            [0, 1], batch_size, p=[1-epsilon, epsilon])\n",
    "        return np.where(should_explore, random_actions, best_actions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_projection(model, next_states, rewards, done_flags, gamma=0.99, n_atoms=51, Vmin=-10, Vmax=10):\n",
    "    batch_size = next_states.size()[0]\n",
    "\n",
    "    d_z = (Vmax - Vmin) / (n_atoms-1)\n",
    "    support = torch.linspace(Vmin, Vmax, n_atoms)\n",
    "    probs = model(next_states)\n",
    "    qvals = support * probs\n",
    "    best_actions = qvals.sum(-1).argmax(-1)\n",
    "    best_actions = best_actions.unsqueeze(1).unsqueeze(1).expand(probs.size(0), 1, probs.size(2))\n",
    "    best_qvals = qvals.gather(1,best_actions).squeeze(1)\n",
    "    \n",
    "    rewards = rewards.unsqueeze(1).expand_as(best_qvals)\n",
    "    done_flags   = done_flags.unsqueeze(1).expand_as(best_qvals)\n",
    "    support = support.unsqueeze(0).expand_as(best_qvals)\n",
    "    \n",
    "    Tz = rewards + (1-done_flags) * gamma * support\n",
    "    Tz = Tz.clamp(Vmin, Vmax)\n",
    "    b = (Tz - Vmin) / (d_z)\n",
    "    l = b.floor().long()\n",
    "    u = b.ceil().long()\n",
    "    \n",
    "    projected_dist = torch.zeros(best_qvals.size())\n",
    "    \n",
    "    offset = torch.linspace(0, (batch_size - 1) * n_atoms, batch_size).long()\\\n",
    "                    .unsqueeze(1).expand(batch_size, n_atoms)\n",
    "\n",
    "    proj_dist = torch.zeros(best_qvals.size())    \n",
    "    proj_dist.view(-1).index_add_(0, (l + offset).view(-1), (best_qvals * (u.float() - b)).view(-1))\n",
    "    proj_dist.view(-1).index_add_(0, (u + offset).view(-1), (best_qvals * (b - l.float())).view(-1))\n",
    "    \n",
    "    return proj_dist    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def td_loss_categorical_dqn(agent, target_network, states, actions, rewards, next_states, done_flags,\n",
    "                    gamma=0.99, device=device):\n",
    "\n",
    "    # convert numpy array to torch tensors\n",
    "    states = torch.tensor(states, device=device, dtype=torch.float)\n",
    "    actions = torch.tensor(actions, device=device, dtype=torch.long)\n",
    "    rewards = torch.tensor(rewards, device=device, dtype=torch.float)\n",
    "    next_states = torch.tensor(next_states, device=device, dtype=torch.float)\n",
    "    done_flags = torch.tensor(done_flags.astype('float32'),device=device,dtype=torch.float)\n",
    "\n",
    "\n",
    "    dist = agent(states)\n",
    "    batch_size, n_actions, n_atoms = dist.size()\n",
    "    actions = actions.unsqueeze(1).unsqueeze(1).expand(batch_size, 1, n_atoms)\n",
    "    dist = dist.gather(1, actions).squeeze(1)\n",
    "    dist.clamp(0.01, 0.99)\n",
    "    \n",
    "    with torch.no_grad():\n",
    "        proj_dist = compute_projection(target_network, next_states, rewards, done_flags, gamma)\n",
    "    \n",
    "    loss = - (proj_dist * dist.log()).sum(1).mean()\n",
    "        \n",
    "    return loss\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "#setup some parameters for training\n",
    "timesteps_per_epoch = 1\n",
    "batch_size = 32\n",
    "total_steps = 3 * 10**4\n",
    "\n",
    "# set exploration epsilon \n",
    "start_epsilon = 1\n",
    "end_epsilon = 0.05\n",
    "eps_decay_final_step = 2 * 10**4\n",
    "\n",
    "# setup spme frequency for loggind and updating target network\n",
    "loss_freq = 50\n",
    "refresh_target_network_freq = 100\n",
    "eval_freq = 1000\n",
    "\n",
    "# to clip the gradients\n",
    "max_grad_norm = 5000\n",
    "\n",
    "#set up random numbers\n",
    "seed=0\n",
    "random.seed(seed)\n",
    "np.random.seed(seed)\n",
    "torch.manual_seed(seed) \n",
    "\n",
    "#init environment\n",
    "ENV_NAME = 'CartPole-v1'\n",
    "env = make_env(ENV_NAME, seed)\n",
    "state_dim = env.observation_space.shape\n",
    "n_actions = env.action_space.n\n",
    "\n",
    "#init agent, target network and Optimizer\n",
    "agent = CategoricalDQN(state_dim, n_actions, epsilon=1).to(device)\n",
    "target_network = CategoricalDQN(state_dim, n_actions, epsilon=1).to(device)\n",
    "target_network.load_state_dict(agent.state_dict())\n",
    "optimizer = torch.optim.Adam(agent.parameters(), lr=1e-4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "buffer size = 10000, epsilon = 0.05000\n"
     ]
    },
    {
     "data": {
      "image/png": "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9a6p3OHwegM45/YAWfjHp4T8ax1GwvbeXA+H+/cetnVXz3tA2NbTQXV8/wzHehoNnG1mm/APHTjVzJ5HdfQdh8klGr2eQiUpnQf0MrNuZhaDfwDuNI9janBmlmBmLQ/+DUwAlh/5qJAxDbg68PfVwDsextJoDr5BBJxHiL3eZmbAk8Aq59wD1Z4K6df7cOUO5dfbzJLNrHXg73jgNGA1If5ah5mwvDfX0+H+vU8DLjGzWDPrBvQC5noQX6M6intAuNZTfd8/w66enHN3Oec6Oue64n/vmeWcuwLV0bccIZdo9HqKCsZJvOacqzSzW4APgEjgP865FR6H1RhSgbf87+FEAS865973NqTgM7OXgLFAezPbBvwOuA941cyuB7YAF3kXYcM4TLnHmtkQ/F0lNgE3eBVfAxkNXAksC4yVAfglof96H67cl4bw650OPBOYtS8CeNU5966ZfUlov9ZhI4zvzTWqz73MObfCzF4FVuKfkfZm51yVJ4E3rnrdA8K4nur1/hnG9VQT/Vv6thpzCTObRyPXkzkXLt2lRUREREREpKkJle67IiIiIiIi0gwpKRURERERERHPKCkVERERERERzygpFREREREREc8oKRURERERERHPKCkVERERERERzygpFREREREREc8oKRURERERERHP/H/LRcK30xrbCwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 1152x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████████████████████████████████████████| 30001/30001 [04:42<00:00, 106.20it/s]\n"
     ]
    }
   ],
   "source": [
    "train_agent(env, agent, target_network, optimizer, td_loss_fn=td_loss_categorical_dqn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "final score(C51 DQN): 229\n"
     ]
    }
   ],
   "source": [
    "final_score = evaluate(\n",
    "  make_env(ENV_NAME),\n",
    "  agent, n_games=30, greedy=True, t_max=1000\n",
    ")\n",
    "print('final score(C51 DQN): {:.0f}'.format(final_score))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Summary\n",
    "\n",
    "In this notebook we saw how to train a DQN agent with experience replay and target networks. We also saw first variant under distributional RL i.e. **Distributional RL - Categorical DQN specifically 51-Atom (C51)**\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
